+use std::iter::FromIterator;
+
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Config, Human};
pub struct Options {
flag_bin: Option<String>,
flag_example: Option<String>,
+ flag_package: Option<String>,
flag_jobs: Option<u32>,
flag_features: Vec<String>,
flag_all_features: bool,
cargo run [options] [--] [<args>...]
Options:
- -h, --help Print this message
- --bin NAME Name of the bin target to run
- --example NAME Name of the example target to run
- -j N, --jobs N Number of parallel jobs, defaults to # of CPUs
- --release Build artifacts in release mode, with optimizations
- --features FEATURES Space-separated list of features to also build
- --all-features Build all available features
- --no-default-features Do not build the `default` feature
- --target TRIPLE Build for the target triple
- --manifest-path PATH Path to the manifest to execute
- -v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
- -q, --quiet No output printed to stdout
- --color WHEN Coloring: auto, always, never
- --message-format FMT Error format: human, json [default: human]
- --frozen Require Cargo.lock and cache are up to date
- --locked Require Cargo.lock is up to date
+ -h, --help Print this message
+ --bin NAME Name of the bin target to run
+ --example NAME Name of the example target to run
+ -p SPEC, --package SPEC Package with the target to run
+ -j N, --jobs N Number of parallel jobs, defaults to # of CPUs
+ --release Build artifacts in release mode, with optimizations
+ --features FEATURES Space-separated list of features to also build
+ --all-features Build all available features
+ --no-default-features Do not build the `default` feature
+ --target TRIPLE Build for the target triple
+ --manifest-path PATH Path to the manifest to execute
+ -v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
+ -q, --quiet No output printed to stdout
+ --color WHEN Coloring: auto, always, never
+ --message-format FMT Error format: human, json [default: human]
+ --frozen Require Cargo.lock and cache are up to date
+ --locked Require Cargo.lock is up to date
If neither `--bin` nor `--example` are given, then if the project only has one
bin target it will be run. Otherwise `--bin` specifies the bin target to run,
examples.push(s);
}
+ let packages = Vec::from_iter(options.flag_package.iter().cloned());
+ let spec = Packages::Packages(&packages);
+
let compile_opts = ops::CompileOptions {
config: config,
jobs: options.flag_jobs,
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: Packages::Packages(&[]),
+ spec: spec,
release: options.flag_release,
mode: ops::CompileMode::Build,
filter: if examples.is_empty() && bins.is_empty() {
Json
}
-#[derive(Clone, Copy, PartialEq, Eq)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Packages<'a> {
All,
Packages(&'a [String]),
}
pub fn compile_with_exec<'a>(ws: &Workspace<'a>,
- options: &CompileOptions<'a>,
+ options: &CompileOptions<'a>,
exec: Arc<Executor>)
-> CargoResult<ops::Compilation<'a>> {
for member in ws.members() {
use std::path::Path;
-use ops::{self, CompileFilter};
-use util::{self, CargoResult, ProcessError};
+use ops::{self, CompileFilter, Packages};
+use util::{self, human, CargoResult, ProcessError};
use core::Workspace;
pub fn run(ws: &Workspace,
options: &ops::CompileOptions,
args: &[String]) -> CargoResult<Option<ProcessError>> {
let config = ws.config();
- let root = ws.current()?;
- let mut bins = root.manifest().targets().iter().filter(|a| {
+ let pkg = match options.spec {
+ Packages::All => unreachable!("cargo run supports single package only"),
+ Packages::Packages(xs) => match xs.len() {
+ 0 => ws.current()?,
+ 1 => ws.members()
+ .find(|pkg| pkg.name() == xs[0])
+ .ok_or_else(|| human(
+ format!("package `{}` is not a member of the workspace", xs[0])
+ ))?,
+ _ => unreachable!("cargo run supports single package only"),
+ }
+ };
+
+ let mut bins = pkg.manifest().targets().iter().filter(|a| {
!a.is_lib() && !a.is_custom_build() && match options.filter {
CompileFilter::Everything => a.is_bin(),
CompileFilter::Only { .. } => options.filter.matches(a),
}
let compile = ops::compile(ws, options)?;
+ assert_eq!(compile.binaries.len(), 1);
let exe = &compile.binaries[0];
let exe = match util::without_prefix(&exe, config.cwd()) {
Some(path) if path.file_name() == Some(path.as_os_str())
Some(path) => path.to_path_buf(),
None => exe.to_path_buf(),
};
- let mut process = compile.target_process(exe, &root)?;
+ let mut process = compile.target_process(exe, &pkg)?;
process.args(args).cwd(config.cwd());
config.shell().status("Running", process.to_string())?;
.with_stdout("")
.with_stderr(""));
}
+
+#[test]
+fn run_multiple_packages() {
+ let p = project("foo")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace]
+
+ [dependencies]
+ d1 = { path = "d1" }
+ d2 = { path = "d2" }
+ d3 = { path = "../d3" } # outside of the workspace
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("foo/src/foo.rs", "fn main() { println!(\"foo\"); }")
+ .file("foo/d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d1"
+ "#)
+ .file("foo/d1/src/lib.rs", "")
+ .file("foo/d1/src/main.rs", "fn main() { println!(\"d1\"); }")
+ .file("foo/d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d2"
+ "#)
+ .file("foo/d2/src/main.rs", "fn main() { println!(\"d2\"); }")
+ .file("d3/Cargo.toml", r#"
+ [package]
+ name = "d3"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("d3/src/main.rs", "fn main() { println!(\"d2\"); }");
+
+ let p = p.build();
+
+ let cargo = || {
+ let mut process_builder = p.cargo("run");
+ process_builder.cwd(p.root().join("foo"));
+ process_builder
+ };
+
+ assert_that(cargo().arg("-p").arg("d1"),
+ execs().with_status(0).with_stdout("d1"));
+
+ assert_that(cargo().arg("-p").arg("d2").arg("--bin").arg("d2"),
+ execs().with_status(0).with_stdout("d2"));
+
+ assert_that(cargo(),
+ execs().with_status(0).with_stdout("foo"));
+
+ assert_that(cargo().arg("-p").arg("d1").arg("-p").arg("d2"),
+ execs()
+ .with_status(1)
+ .with_stderr_contains("[ERROR] Invalid arguments."));
+
+ assert_that(cargo().arg("-p").arg("d3"),
+ execs()
+ .with_status(101)
+ .with_stderr_contains("[ERROR] package `d3` is not a member of the workspace"));
+}